package org.farming.plants;
/**
 * Tree, Plant class
 * @author DEADBEEF
 * @version 0.01a
 * @note Whoel class is untested
**/
public class Trees extends Plants
{

    public static enum Tree implements Plants.TreeEnum {
        UNKNOWN ( -3, "Unknown",     0,  0,  0,    "Unknown",        0,    "Unknown",     "",            false, 0,  0,    "",            0,    0,    "",                6043, "",             -1   ),
        NONE    ( -2, "None",        0,  0,  0,    "None",           0,    "None",        "",            false, 0,  0,    "",            0,    0,    "",                6043, "Tree Patch",   -1   ), 
        WEEDS   ( -1, "Weeds",       0,  0,  0,    "Weeds",          6055, "Weeds",       "",            false, 0,  0,    "",            0,    0,    "",                6043, "Tree Patch",   -1   ),
        EMPTY   ( 0,  "Empty",       0,  0,  0,    "Empty",          0,    "Empty",       "",            false, 0,  0,    "",            0,    0,    "",                6043, "Tree Patch",   -1   ),
        OAK	    ( 8,  "Oak Tree",    15, 5,  5370, "Oak sapling", 	  1521, "Oak logs",    "Oak tree",    false, 15, 5312, "Acorn",       5358, 5364, "Oak seedling",    6043, "Oak roots",    -1   ),
        WILLOW  ( 15, "Willow Tree", 30, 7,  5371, "Willow sapling", 1519, "Willow logs", "Willow tree", false, 30, 5313, "Willow seed", 5359, 5365, "Willow seedling", 6045, "Willow roots", 5933 ),
        MAPLE	( 24, "Maple Tree",  45, 8,  5372, "Maple sapling",  1517, "Maple logs",  "Maple tree",  false, 45, 5314, "Maple seed",  5360, 5366, "Maple seedling",  6047, "Maple roots",  -1   ),
        YEW	    ( 35, "Yew Tree",    60, 10, 5373, "Yew sapling",    1515, "Yew logs",    "Yew tree",    false, 60, 5315, "Yew seed",    5361, 5367, "Yew seedling",    6049, "Yew roots",    -1   ),
        MAGIC	( 48, "Magic Tree",  75, 12, 5374, "Magic sapling",  1513, "Magic logs",  "Magic tree",  false, 75, 5316, "Magic seed",  5362, 5368, "Magic seedling",  6051, "Magic roots",  -1   );
      
        private final int id, level, stages, seedId, itemId, chopLevel, preSeedId, seedlingId, seedlingWaterId, rootsId, branchesId;   
        private final String seedString, itemString, interactString, preSeedString, seedlingString, rootsString, name;     
        private final boolean canNote;   
        /**
         * Tree Enum
         * Interface(PlantEnum) params
         * @param id Our unique id and offset for the plant
         * @param name The reference for this plant which we can display to the user
         * @param level The farming level required to plant
         * @param stages How many growth stages the plant has (from first planted to harvestable inclusive)
         * @param seedId, Item id of the sapling (for consistency we treat the sapling as the seed)
         * @param seedString, Item string of the sapling
         * @param itemId, Item id of the harvested plant
         * @param itemString, Item string of the harvested plant
         * @param interactString, String of the plant when grown
         * @param canNote, Whether the leprechaun can note this plant (noted item id's are +1 of the regular id)
         * Interface(TreeEnum) params    
         * @param preSeedId Item id of the actual seed for the tree
         * @param preSeedString Item string of the actual seed for the tree
         * @param potId Item id when planted in a pot and not watered
         * @param potWaterId Item id when planted in a pot and watered
         * @param potString Item string when it has been planted in a pot
         * Local params
         * @param rootsId, Item id of the roots
         * @param rootsString, Item string of the roots
         * @param branchesId, Item id of the trees branches, -1 if tree cannot get branches
        **/
        Tree(
            int id, 
            String name,
            int level, 
            int stages, 
            int seedId, 
            String seedString, 
            int itemId, 
            String itemString, 
            String interactString, 
            boolean canNote,
            int chopLevel,
            int preSeedId,
            String preSeedString,
            int seedlingId,
            int seedlingWaterId,
            String seedlingString,
            int rootsId,
            String rootsString,
            int branchesId
        ) {
            this.id              = id;
            this.name            = name;
            this.level           = level;
            this.stages          = stages;
            this.seedId          = seedId;
            this.itemId          = itemId;
            this.seedString      = seedString;
            this.itemString      = itemString;
            this.interactString  = interactString;
            this.canNote         = canNote;
            this.chopLevel       = chopLevel;
            this.preSeedId       = preSeedId;
            this.preSeedString   = preSeedString;
            this.seedlingId      = seedlingId;
            this.seedlingWaterId = seedlingWaterId;
            this.seedlingString  = seedlingString;
            this.rootsId         = rootsId;
            this.rootsString     = rootsString;
            this.branchesId      = branchesId;
        }
        //Interface (Plant) methods
        public int id()                {return id;}
        public int level()             {return level;}
        public int stages()            {return stages;}
        public int seedId()            {return seedId;}
        public int itemId()            {return itemId;}
        public String seedString()     {return seedString;}
        public String itemString()     {return itemString;}
        public String interactString() {return interactString;}
        public boolean canNote()       {return canNote;}
        public int noteId()            {return canNote?(itemId+1):itemId;}
        public String toString()       {return name;}
        //Interface (Tree) methods
        public int chopLevel()         {return chopLevel;}
		public int preSeedId()         {return preSeedId;}
		public String preSeedString()  {return preSeedString;}
		public int seedlingId()        {return seedlingId;}
		public int seedlingWaterId()   {return seedlingWaterId;}
		public String seedlingString() {return seedlingString;}
        //Local methods
		public int rootsId()           {return rootsId;}
		public String rootsString()    {return rootsString;}
        public boolean hasBranches()   {return branchesId!=-1;}
        public int branchesId()        {return branchesId;}
    }

   /**
    * This was designed to be a static method, however static and abstract don't mix so this will have to do
    * 
    * @param bits The byte for the herb patch we want the state for
    * @return The calculated state enum
   **/
    public State getState(int bits)
    {
        bits = bits&255;//Cleanse
        int stateBits = (bits&192)>>6;//Get 7&8th bits
        int plantBits = bits&63;//Clear 7&8th bits
        if(stateBits==0x00||stateBits==0x03){
            Tree p = getPlant(bits);
            if(stateBits==0x03&&p.hasBranches()){       return State.BRANCHES;
            }else{
                int offset = plantBits-p.id()-p.stages;
                if(offset>=0){ 
                    if(offset==0){                      return State.CHECK_HEALTH;
                    }else if(offset==1){                return State.READY;
                    }else if(offset==2){                return State.CHOPPED;
                    }else{                              return State.UNKNOWN;}
                }else{                                  return State.GROWING;}}
        }else if(stateBits==0x01){                      return State.WATERED;
        }else if(stateBits==0x01){                      return State.DISEASED;
        }else if(stateBits==0x02){                      return State.DEAD;
        }else{                                          return State.UNKNOWN;}
   }
   
   /**
    * This was designed to be a static method, however static and abstract don't mix so this will have to do
    * 
    * @param bits The byte for the patch we want the tree for
    * @return The calculated plant enum
   **/
    public Tree getPlant(int bits)
    {
        bits = bits&255;//Cleanse
        int stateBits = (bits&192)>>6;//Get 7&8th bits
        int plantBits = bits&63;//Clear 7&8th bits
        if((stateBits==0)&&((plantBits==0x03))){           		        return Tree.EMPTY;
        }else if((stateBits==0)&&(plantBits>=0x00)&&(plantBits<=0x02)){ return Tree.WEEDS;
        }else if((plantBits>=0x08)&&(plantBits<=0x0E)){                 return Tree.OAK;
        }else if((plantBits>=0x0F)&&(plantBits<=0x17)){                 return Tree.WILLOW;
        }else if((plantBits>=0x18)&&(plantBits<=0x22)){                 return Tree.MAPLE;
        }else if((plantBits>=0x23)&&(plantBits<=0x2F)){                 return Tree.YEW;
        }else if((plantBits>=0x30)&&(plantBits<=0x3E)){                 return Tree.MAGIC;
        }else{                                                          return Tree.UNKNOWN;}
    }
   
   /**
    * This was designed to be a static method, however static and abstract don't mix so this will have to do
    * 
    * @param bits The byte for the herb patch we want the stage for
    * @return The calculated stage
   **/
    public int getStage(int bits)
    {
        bits = bits&255;//Cleanse
        int plantBits = bits&63;//Clear 7&8th bits
        return getStagePlant(getPlant(bits), plantBits);
    }
    private int getStagePlant(Tree plant, int plantBits)
    {
        switch(plant)
        {
            case EMPTY:
            case WEEDS:
            case UNKNOWN:
                return 0;
            default:
                return ((plantBits-plant.id()+1)>plant.stages())?plant.stages():(plantBits-plant.id()+1);
        }
    }
    
   /**
    * This was designed to be a static method, however static and abstract don't mix so this will have to do
    * 
    * @param bits The byte for the herb patch we want the stage for
    * @return The calculated number of branches that can be pruned, returns -1 in cases where branches can never be pruned (e.g. not a willow tree)
   **/
    public int getBranchCount(int bits)
    {
        return (getState(bits)==State.BRANCHES)?(bits&15):0;
    }
}
/*
## Tree
format: sspp pppp
- plant types and growth states (p bits):
-- 0x00 - 0x03: layers of weeds removed (0x00 meaning no weeds removed, 0x03 meaning all weeds removed), iff both state bits are 0
-- 0x08 - 0x0e: oak tree (0x0c is ready to check-health, 0x0d is ready to chop down, 0x0e is oak tree stump)
-- 0x0f - 0x17: willow tree (0x15 is ready to check-health, 0x16 is ready to chop down, 0x17 is willow tree stump)
-- 0x18 - 0x22: maple tree (0x20 is ready to check-health, 0x21 is ready to chop down, 0x22 is maple tree stump)
-- 0x23 - 0x2f: yew tree (0x2d is ready to check-health, 0x2e is ready to chop down, 0x2f is yew tree stump)
-- 0x30 - 0x3e: magic tree (0x3c is ready to check-health, 0x3d is ready to chop down, 0x3e is magic tree stump)
- states (s bits):
- 0x00: growing
- 0x01: diseased
- 0x02: dead
- 0x03: has branches (willow tree only), low nibble contains number of branches already taken or remaining (in-game testing is needed)

locations:
- unknown, setting 502 
- unknown, bits 11-18 of setting 830
*/